package web

import (
	"gitee.com/youbeiwuhuan/gin-practice/gin-simple-zap/global"
	"gitee.com/youbeiwuhuan/gin-practice/gin-simple-zap/global/config"
	"gitee.com/youbeiwuhuan/gin-practice/gin-simple-zap/internal/web/controller"
	"gitee.com/youbeiwuhuan/gin-practice/gin-simple-zap/internal/web/middleware/auths"
	"gitee.com/youbeiwuhuan/gin-practice/gin-simple-zap/internal/web/middleware/cors"
	"gitee.com/youbeiwuhuan/gin-practice/gin-simple-zap/tools/gins"
	"gitee.com/youbeiwuhuan/gin-practice/gin-simple-zap/valid"
	"github.com/gin-contrib/pprof"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net/http"
	"strconv"
	"sync"
	"time"
)

// 该路由主要设置 后台管理系统等后端应用路由

func InitWebRouter(ginConfig gins.GinConfig, logger *zap.Logger) *gin.Engine {
	var router *gin.Engine
	// 非调试模式（生产模式） 日志写到日志文件
	if ginConfig.AppDebug == false {
		//【生产模式】
		// 根据 gin 官方的说明：[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
		// 如果部署到生产环境，请使用以下模式：
		// 1.生产模式(release) 和开发模式的变化主要是禁用 gin 记录接口访问日志，
		// 2.go服务就必须使用nginx作为前置代理服务，这样也方便实现负载均衡
		// 3.如果程序发生 panic 等异常使用自定义的 panic 恢复中间件拦截、记录到日志
		router = gins.ReleaseRouter(logger)

	} else {
		// 调试模式，开启 pprof 包，便于开发阶段分析程序性能
		router = gin.Default()
		router.Use(GinLogger(logger))
		pprof.Register(router)
	}

	// 设置可信任的代理服务器列表,gin (2021-11-24发布的v1.7.7版本之后出的新功能)
	_ = router.SetTrustedProxies(nil)

	//根据配置进行设置跨域
	if ginConfig.AllowCrossDomain {
		router.Use(cors.Next())
	}

	router.GET("/", func(context *gin.Context) {
		context.String(http.StatusOK, "HelloWorld,这是后端模块")
	})

	//处理静态资源（不建议gin框架处理静态资源，参见 public/readme.md 说明 ）
	router.Static("/public", "./public")             //  定义静态资源路由与实际目录映射关系
	router.StaticFS("/dir", http.Dir("./public"))    // 将public目录内的文件列举展示
	router.StaticFile("/abcd", "./public/readme.md") // 可以根据文件名绑定需要返回的文件名

	return router
}

// GinLogger 创建一个 Gin 中间件，使用 zap logger 记录请求日志
func GinLogger(logger *zap.Logger) gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()
		// 处理请求
		c.Next()

		// 日志记录请求信息
		end := time.Now()
		latency := end.Sub(start)
		logger.Info("请求完成",
			zap.String("method", c.Request.Method),
			zap.String("path", c.Request.URL.Path),
			zap.String("status", strconv.Itoa(c.Writer.Status())),
			zap.Duration("latency", latency),
		)
	}
}

var (
	webRunOnce sync.Once
)

func RunWeb() {
	webRunOnce.Do(func() {
		global.ValidateObj = valid.Init()
		global.RootRouter = InitWebRouter(config.TotalConfig.Gin, global.ZapLog)
		global.RootRouter.Use(auths.UserId())
		// 业务逻辑
		controller.Start(global.RootRouter)

		global.RootRouter.Run(":" + strconv.Itoa(config.TotalConfig.Gin.Port))
	})

}
